/*
 * Copyright (c) 2010-2013 Ruben Chakhmakhchyan. All rights reserved.
 * 
 * This file contains Original Code and/or Modifications of Original Code
 * as defined in and that are subject to the Eclipse Public License
 * Version 1.0 (the 'License'). You may not use this file except in
 * compliance with the License. Please obtain a copy of the License at
 * http://opensource.org/licenses/EPL-1.0 and read it before using this file.
 */

#include "base64.h"


uint_t base64Length( uint_t dataLength )
{
    if ( dataLength < 3 ) return 0;

    uint_t lengthMod3 = dataLength % 3;
    uint_t length3 = lengthMod3 == 0 ? dataLength : ( dataLength + 3 - lengthMod3 );

    uint_t bufferLength = ( length3 / 3 ) << 2;

    return bufferLength;
}

bool base64Encode( char* pbuffer, byte_t* pdata, uint_t length )
{
    // 111111.11 1111.1111 11.111111

    if ( length < 3 ) return false;

    char* alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=";

    byte_t* p = 0;
    char* bp = pbuffer;

    int j = 0;
    for( uint_t i = 0; i < length; i += 3, j += 4 )
    {
        p = pdata + i;
        bp = pbuffer + j;

        byte_t p1 = ( *p & 0xFC ) >> 2; // ~11
        byte_t p2 = ( ( *p & 0x03 ) << 4 ) + ( i + 1 < length ? ( ( *( p + 1 ) & 0xF0 ) >> 4 ) : 0 );
        byte_t p31 = ( ( i + 1 < length ) ? ( ( *( p + 1 ) & 0xF ) << 2 ) : 64 );
        byte_t p3 = ( p31 == 64 ) ? 64 : ( p31 + ( ( i + 2 < length ) ? ( ( *( p + 2 ) & 0xC0 ) >> 6 ) : 0 ) );
        byte_t p4 = ( i + 2 < length ) ? *( p + 2 ) & 0x3F : 64;

        *bp = alphabet[ p1 ];
        *( bp + 1 ) = alphabet[ p2 ];
        *( bp + 2 ) = alphabet[ p3 ];
        *( bp + 3 ) = alphabet[ p4 ];
    }

    return true; //pbuffer != 0;
}
